#include <FGraphics.h>
#include <FMedia.h>
#include "FormJogo.h"
#include "view/FormMgr.h"
#include "db/InfoDB.h"

using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::Ui;
using namespace Osp::Ui::Controls;
using namespace Osp::Graphics;
using namespace Osp::Media;

FormJogo::FormJogo(void) {
}

FormJogo::~FormJogo(void) {
}

bool FormJogo::Initialize() {
	Form::Construct(L"IDF_FORM_JOGO");
	return true;
}

void FormJogo::InitializeLabels() {
	__pLabelJogador = static_cast<Label*> (GetControl(L"IDC_LABEL_JOGADOR"));
	if (__pLabelJogador != null)
	{
		__pLabelJogador->SetText(controlador->GetJogador()->ToString());
	}
	__pLabelJogadorAI1 = static_cast<Label*>(GetControl(L"IDC_LABEL_JOGADOR_PC1"));
	if (__pLabelJogadorAI1 != null)
	{
		__pLabelJogadorAI1->SetText(controlador->GetJogador(1)->ToString());
	}
	__pLabelJogadorAI2 = static_cast<Label*>(GetControl(L"IDC_LABEL_JOGADOR_PC2"));
	if (__pLabelJogadorAI2 != null)
	{
		__pLabelJogadorAI2->SetText(controlador->GetJogador(2)->ToString());
	}
	__pLabelJogadorAI3 = static_cast<Label*>(GetControl(L"IDC_LABEL_JOGADOR_PC3"));
	if (__pLabelJogadorAI3 != null)
	{
		__pLabelJogadorAI3->SetText(controlador->GetJogador(3)->ToString());
	}

	__pLabelPot = static_cast<Label*>(GetControl(L"IDC_LABEL_POT"));
	if (__pLabelPot != null)
	{
		__pLabelPot->SetText("Pot: $0");
		__pLabelPot->SetShowState(false);
	}

	__pLabelVencedor = static_cast<Label*>(GetControl(L"IDC_LABEL_VENCEDOR"));
	if (__pLabelVencedor != null)
	{
		__pLabelVencedor->SetShowState(false);
	}
}

void FormJogo::InitializeButtons() {

	__pButtonLeave = static_cast<Button *> (GetControl(L"IDC_BUTTON_LEAVE"));
	if (__pButtonLeave != null)
	{
		__pButtonLeave->SetActionId(ID_BUTTON_LEAVE);
		__pButtonLeave->AddActionEventListener(*this);
		__pButtonLeave->SetShowState(false);
	}

	__pButtonFoldBlind = static_cast<Button *> (GetControl(L"IDC_BUTTON_FOLD_BLIND"));
	if (__pButtonFoldBlind != null)
	{
		__pButtonFoldBlind->SetActionId(ID_BUTTON_FOLD_BLIND);
		__pButtonFoldBlind->AddActionEventListener(*this);
		__pButtonFoldBlind->SetShowState(false);
	}

	__pButtonBlind = static_cast<Button *> (GetControl(L"IDC_BUTTON_BLIND"));
	if (__pButtonBlind != null)
	{
		__pButtonBlind->SetActionId(ID_BUTTON_BLIND);
		__pButtonBlind->AddActionEventListener(*this);
		__pButtonBlind->SetShowState(false);
	}

	__pButtonRaise = static_cast<Button *> (GetControl(L"IDC_BUTTON_RAISE"));
	if (__pButtonRaise != null)
	{
		__pButtonRaise->SetActionId(ID_BUTTON_RAISE);
		__pButtonRaise->AddActionEventListener(*this);
		__pButtonRaise->SetShowState(false);
	}

	__pButtonCall = static_cast<Button *> (GetControl(L"IDC_BUTTON_CALL"));
	if (__pButtonCall != null)
	{
		__pButtonCall->SetActionId(ID_BUTTON_CALL);
		__pButtonCall->AddActionEventListener(*this);
		__pButtonCall->SetShowState(false);
	}

	__pButtonFold = static_cast<Button *> (GetControl(L"IDC_BUTTON1"));
	if (__pButtonFold != null)
	{
		__pButtonFold->SetActionId(ID_BUTTON_BLIND);
		__pButtonFold->AddActionEventListener(*this);
		__pButtonFold->SetShowState(false);
	}

	__pButtonBet = static_cast<Button *> (GetControl(L"IDC_BUTTON_BET"));
	if (__pButtonBet != null)
	{
		__pButtonBet->SetActionId(ID_BUTTON_BET);
		__pButtonBet->AddActionEventListener(*this);
		__pButtonBet->SetShowState(false);
	}

	__pButtonCheck = static_cast<Button *> (GetControl(L"IDC_BUTTON_CHECK"));
	if (__pButtonCheck != null)
	{
		__pButtonCheck->SetActionId(ID_BUTTON_CHECK);
		__pButtonCheck->AddActionEventListener(*this);
		__pButtonCheck->SetShowState(false);
	}
}

void FormJogo::InitializeList()
{
	__pListApostas = static_cast<List *> (GetControl(L"IDC_LIST_APOSTAS"));
	if(__pListApostas != null){
		__pListApostas->AddItemEventListener(*this);
		__pListApostas->SetShowState(false);
	}

	Image decoder;
	decoder.Construct();
	Bitmap* bitmap;

	for (int i = 0; i <= 9; ++i) {
		String s = "/Home/apostas/bet-";
		s.Append(i);
		s.Append(".png");
		bitmap = decoder.DecodeN(s, BITMAP_PIXEL_FORMAT_ARGB8888);
		__pListApostas->AddItem(null, null, bitmap, null, 199+i);
		delete bitmap;
	}
}

result FormJogo::OnTerminating(void) {
	return E_SUCCESS;
}

result FormJogo::OnInitializing(void) {
	result r = E_SUCCESS;

	valorAposta = 1;

	desenhadora = new Desenhadora();
	desenhadora->Construct();

	controlador = Controlador::GetInstance();
	controlador->Construct();
	controlador->SetListener(this);

	controlador->AddJogadores(3);

	timer = new SmartTimer();
	timer->Construir(*this);

	timer->Iniciar(TA_INICIAR_PARTIDA, 1000);

	InitializeLabels();
	InitializeButtons();
	InitializeList();

	AppLog("passou aqui");

	return r;
}

void FormJogo::RequestFormMenu() {
	Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
	FormMgr *pFormMgr = static_cast<FormMgr*> (pFrame->GetControl("FormMgr"));
	if (pFormMgr != null) {
		pFormMgr->SendUserEvent(FormMgr::REQUEST_FORM_MENU, null);
	}
}

void FormJogo::ButtonLeavePressed()
{
	DatabaseManager db;
	db.Construct();

	db.Atualizar(new InfoDB(controlador->GetJogador()->GetNome(), controlador->GetJogador()->GetDinheiro()));

	Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
	FormMgr *pFormMgr = static_cast<FormMgr *> (pFrame->GetControl("FormMgr"));
	if (pFormMgr != null)
		pFormMgr->SendUserEvent(FormMgr::REQUEST_FORM_MENU, null);
}

void FormJogo::AtualizaInfoJogador()
{
	__pLabelJogador->SetText(controlador->GetJogador()->ToString());
}

void FormJogo::ButtonFoldBlindPressed()
{
	controlador->GetJogador()->Desistir();
	AtualizaInfoJogador();
	controlador->InicioRodadaDeAposta();
	SetShowStateBlindButtons(false);
	RequestRedraw(true);
}

void FormJogo::ButtonBlindPressed()
{
	controlador->GetJogador()->Apostar(controlador->GetBlind());
	AtualizaInfoJogador();
	controlador->InicioRodadaDeAposta();
	SetShowStateBlindButtons(false);
	RequestRedraw(true);
}

void FormJogo::ButtonRaisePressed()
{
	controlador->GetJogador()->AumentarApostaPara(controlador->GetMaiorApostaRodada() + valorAposta);
	controlador->JogadorJogou(new Acao(COBRIR, controlador->GetMaiorApostaRodada() + valorAposta));
}

void FormJogo::ButtonCallPressed()
{
	controlador->GetJogador()->AumentarApostaPara(controlador->GetMaiorApostaRodada());
	controlador->JogadorJogou(new Acao(COBRIR, controlador->GetMaiorApostaRodada()));
	SetShowStateControlesAposta(false);
}

void FormJogo::ButtonFoldPressed()
{
	controlador->GetJogador()->Desistir();
	controlador->JogadorJogou(new Acao(DESISTIR, 0));
	SetShowStateControlesAposta(false);
}

void FormJogo::ButtonBetPressed()
{
	if(controlador->GetJogador()->PodeApostar(valorAposta)){
		controlador->GetJogador()->Apostar(valorAposta);
		controlador->JogadorJogou(new Acao(APOSTAR, valorAposta));
		SetShowStateControlesAposta(false);
	}else{
		//todo
	}
}

void FormJogo::ButtonCheckPressed()
{
	controlador->GetJogador()->Passar();
	controlador->JogadorJogou(new Acao(PASSAR, 0));
	SetShowStateControlesAposta(false);
}

void FormJogo::AtualizaInfoJogadoresAI() {
	__pLabelJogadorAI1->SetText(controlador->GetJogador(1)->ToString());
	__pLabelJogadorAI2->SetText(controlador->GetJogador(2)->ToString());
	__pLabelJogadorAI3->SetText(controlador->GetJogador(3)->ToString());
}

void FormJogo::AtualizaBotoesAposta()
{
	String btBetSrt = "Bet $";
	btBetSrt.Append(valorAposta);
	String btRaiseStr = "Raise $";
	btRaiseStr.Append(valorAposta);
	String btCallStr = "Call $";
	btCallStr.Append(controlador->GetMaiorApostaRodada());
	__pButtonBet->SetText(btBetSrt);
	__pButtonRaise->SetText(btRaiseStr);
	__pButtonCall->SetText(btCallStr);
}

void FormJogo::SetShowStateBlindButtons(bool t)
{
	String textButtontBlind = "Bet ($";
	textButtontBlind.Append(controlador->GetBlind());
	textButtontBlind.Append("");

	String textLabelPot = "Pot $";
	textLabelPot.Append(controlador->GetApostaAcumulada());
	__pLabelPot->SetText(textLabelPot);
	__pLabelPot->SetShowState(! t);

	__pButtonBlind->SetShowState(t);
	__pButtonLeave->SetShowState(t);
	__pButtonFoldBlind->SetShowState(t);
}

void FormJogo::SetShowStateControlesAposta(bool b)
{
	AppLog("Debug 1");
	AtualizaBotoesAposta();
	AppLog("Debug 2");

	//__pLabelJogadorAI1->SetShowState(!b);
	//__pLabelJogadorAI3->SetShowState(!b);

	if(b){
		AppLog("Debug 3");
		if(controlador->GetMaiorApostaRodada()== 0){
			__pButtonBet->SetShowState(b);
			__pButtonCheck->SetShowState(b);
			AppLog("Debug 4");
		}else{
			__pButtonRaise->SetShowState(b);
			__pButtonCall->SetShowState(b);
			__pButtonFold->SetShowState(b);
			AppLog("Debug 5");
		}
	}else{
		__pButtonBet->SetShowState(b);
		__pButtonCheck->SetShowState(b);
		__pButtonRaise->SetShowState(b);
		__pButtonCall->SetShowState(b);
		__pButtonFold->SetShowState(b);
		AppLog("Debug 6");

	}

	__pListApostas->SetShowState(b);

}

void FormJogo::OnTimerExpired(Osp::Base::Runtime::Timer & timer) {
	int actionId = ((SmartTimer*) &timer)->actionId;

	switch (actionId) {
	case TA_INICIAR_PARTIDA:
		controlador->InicioPartida();
		break;
	case TA_DAR_CARTAS:
		controlador->DarCartasJogadores();
		break;
	case TA_SOLICITAR_BLIND:
		controlador->SolicitarBlind();
		break;
	case TA_INICIAR_RODADA:
		controlador->InicioRodadaDeAposta();
		break;
	case TA_INICIAR_JOGADA_VEZ:
		controlador->InicioJogadaDaVez();
		break;
	case TA_TERMINAR_RODADA:
		controlador->FimRodadaAposta();
		break;
	case TA_TERMINAR_PARTIDA:
		controlador->FimPartida();
		break;

	default:
		break;
	}
}

void FormJogo::OnItemStateChanged(const Osp::Ui::Control & source, int index, int itemId, Osp::Ui::ItemStatus status)
{
	AppLog("Lancou");
	int apostas[]  = {1, 2, 5, 10, 25, 50, 100, 200, 500};

	int aposta = index-1;

	if(aposta == -1){
		valorAposta = 0;
	}else{
		valorAposta += apostas[aposta];
		AppLog("Aposta = %d", valorAposta);
	}

	AtualizaBotoesAposta();
	RequestRedraw(true);
}

result FormJogo::OnDraw() {
	result r = E_SUCCESS;

	//AtualizaInfoJogador();
	//AtualizaInfoJogadoresAI();

	Canvas* pCanvas = GetCanvasN();

	if (pCanvas) {
		pCanvas->Clear();

		desenhadora->DesenhaBackground(pCanvas);

		__pLabelVencedor->SetShowState(false);

		switch (showMode) {
		case SM_DEU_CARTAS:
			desenhadora->DesenhaMao(controlador->GetJogador()->GetMao(), 100,
					170, pCanvas);
			break;
		case SM_BLIND_REQ:
			desenhadora->DesenhaMao(controlador->GetJogador()->GetMao(), 100,
					170, pCanvas);
			break;
		case SM_APOSTANDO:
			desenhadora->DesenhaMao(controlador->GetJogador()->GetMao(), 100,
					170, pCanvas);
			desenhadora->DesenhaMao(controlador->GetMesa(), 60, 90, pCanvas);
			break;
		case SM_PAGANDO:
			__pLabelVencedor->SetShowState(true);
			break;
		default:
			desenhadora->DesenhaMao(controlador->GetJogador()->GetMao(), 100,
					170, pCanvas);
			desenhadora->DesenhaMao(controlador->GetMesa(), 60, 90, pCanvas);
			break;
		}

		pCanvas->Show();

		delete pCanvas;
	}

	return r;
}

void FormJogo::OnActionPerformed(const Osp::Ui::Control& source, int actionId) {
	switch (actionId) {
	case ID_BUTTON_LEAVE:
		ButtonLeavePressed();
		break;
	case ID_BUTTON_FOLD_BLIND:
		ButtonFoldBlindPressed();
		break;
	case ID_BUTTON_BLIND:
		ButtonBlindPressed();
		break;
	case ID_BUTTON_RAISE:
		ButtonRaisePressed();
		break;
	case ID_BUTTON_CALL:
		ButtonCallPressed();
		break;
	case ID_BUTTON_FOLD:
		ButtonFoldPressed();
		break;
	case ID_BUTTON_BET:
		ButtonBetPressed();
		break;
	case ID_BUTTON_CHECK:
		ButtonCheckPressed();
		break;
	default:
		break;
	}
}

void FormJogo::OnInicioPartida() {
	AppLog("FormJogo::OnInicioPartida");
	showMode = SM_INICIO_PARTIDA;
	timer->Iniciar(TA_DAR_CARTAS, 1000);
}

void FormJogo::OnDarCartasJogadores() {
	AppLog("FormJogo::OnDarCartasJogadores");
	showMode = SM_DEU_CARTAS;
	timer->Iniciar(TA_SOLICITAR_BLIND, 500);
	RequestRedraw(true);
}



void FormJogo::OnSolicitarBlind() {
	AppLog("FormJogo::OnSolicitarBlind");
	showMode = SM_BLIND_REQ;
	AtualizaInfoJogadoresAI();

	SetShowStateBlindButtons(true);
	RequestRedraw(true);
}

void FormJogo::OnRecebeuBlinds() {
	AppLog("FormJogo::OnRecebeuBlinds");
	showMode = SM_BLIND_OK;
	timer->Iniciar(TA_INICIAR_RODADA, 500);
}

void FormJogo::OnInicioRodadaDeAposta() {
	AppLog("FormJogo::OnInicioRodadaAposta");
	valorAposta = 1;
	showMode = SM_APOSTANDO;
	timer->Iniciar(TA_INICIAR_JOGADA_VEZ, 500);
	RequestRedraw(true);
}

void FormJogo::OnInicioJogadaJogador()
{
	AppLog("FormJogo::OnInicioJogadaJogador");
	showMode = SM_APOSTA_JOGADOR;

	SetShowStateControlesAposta(true);
	RequestRedraw(true);
}

void FormJogo::OnJogadorJogou(Acao *acao) {
	AppLog("FormJogo::OnJogadorJogou");
	AtualizaInfoJogador();
	AtualizaInfoJogadoresAI();
	RequestRedraw(true);

	if (controlador->QuantidadeJogadoresJogando() == 1) {
		controlador->PagaVencedor();
	}else{
		controlador->ProximoJogador();
		if(controlador->RodadaPodeTerminar()){
			timer->Iniciar(TA_TERMINAR_RODADA, 700);
		}else{
			timer->Iniciar(TA_INICIAR_JOGADA_VEZ, 2000);
		}

	}
}

void FormJogo::OnFimRodadaAposta() {
	AppLog("FormJogo::OnFimRodadaAposta");
	timer->Iniciar(TA_INICIAR_RODADA, 1000);
}

void FormJogo::OnPagaVencedor(Jogador* j, Combinacao* c) {
	AppLog("FormJogo::OnPagaVencedor");
	String str = "";
	str.Append(j->GetNome());
	str.Append(" WIN\n");
	str.Append(c->ToString());
	__pLabelVencedor->SetText(str);
	showMode = SM_PAGANDO;
	timer->Iniciar(3000, TA_TERMINAR_PARTIDA);
	RequestRedraw(true);

}

void FormJogo::OnFimPartida() {
	AppLog("FormJogo::OnFimPartida");
	showMode = SM_FIM_PARTIDA;
}
